﻿using Unity.Burst;
using Unity.Collections;
using Unity.Entities;
using Unity.Jobs;

[UpdateInGroup(typeof(LateSimulationSystemGroup), OrderLast = true)]
partial struct ResetEventsSystem : ISystem
{
    private NativeArray<JobHandle> jobHandleNativeArray;
    private NativeList<Entity> onBarrackUnitQueueChangedEntityList;
    [BurstCompile]
    public void OnCreate(ref SystemState state)
    {
        jobHandleNativeArray = new NativeArray<JobHandle>(4, Allocator.Persistent);
        onBarrackUnitQueueChangedEntityList = new NativeList<Entity>(Allocator.Persistent);
    }

    //使用非托管对应 Monobehaover 不能使用Burst编译 ，但这里是发送给Job系统工作 本质上没有过多影响
    //[BurstCompile]
    public void OnUpdate(ref SystemState state)
    {
        if (SystemAPI.HasSingleton<BuildingHQ>())
        {
            Health health = SystemAPI.GetComponent<Health>(SystemAPI.GetSingletonEntity<BuildingHQ>());
            if (health.onDead)
            {
                DotsEventManager.Instance.TriggerOnHQDeadChanged();
            }
        }
        //将这些作业系统
        jobHandleNativeArray[0] = new ResetSelectedEventsJob().ScheduleParallel(state.Dependency);
        jobHandleNativeArray[1] = new ResetHealthEventsJob().ScheduleParallel(state.Dependency);
        jobHandleNativeArray[2] = new ResetMeleeAttackEventsJob().ScheduleParallel(state.Dependency);
        jobHandleNativeArray[3] = new ResetShootAttackEventsJob().ScheduleParallel(state.Dependency);

        
        //NativeList<Entity> onBarrackUnitQueueChangedEntityList = new NativeList<Entity>(Allocator.TempJob);//并行写入需要传递 TempJob类型
        onBarrackUnitQueueChangedEntityList.Clear();
        new ResetBuildingBarracksEventsJob()
        {
            onUnitQueueChangedEntityList = onBarrackUnitQueueChangedEntityList.AsParallelWriter(),//由于是并行任务所有要转换成并行写入
        }.ScheduleParallel(state.Dependency)
        .Complete();//调用作业立即完成返回结果(Job不调用只是加入到作业中并不会立即执行所有这里要这样写)

        //通过单例非Dots类向外部传递事件
        DotsEventManager.Instance.TriggerOnBarracksUnitQueueChanged(onBarrackUnitQueueChangedEntityList);

        state.Dependency = JobHandle.CombineDependencies(jobHandleNativeArray);
        //foreach (RefRW<Selected> selected in SystemAPI.Query<RefRW<Selected>>().WithPresent<Selected>())
        //{
        //    selected.ValueRW.onSelected = false;
        //    selected.ValueRW.onDeselected = false;
        //}

        //foreach (RefRW<Health> health in SystemAPI.Query<RefRW<Health>>())
        //{
        //    health.ValueRW.onHealthChanged = false;
        //}

        //foreach (RefRW<ShootAttack> shootAttack in SystemAPI.Query<RefRW<ShootAttack>>())
        //{
        //    shootAttack.ValueRW.onShoot.isTriggered = false;
        //}
    }

    [BurstCompile]
    public void OnDestroy(ref SystemState state)
    {
        jobHandleNativeArray.Dispose();
        onBarrackUnitQueueChangedEntityList.Dispose();
    }
}

//定义任务
[BurstCompile]
public partial struct ResetShootAttackEventsJob : IJobEntity
{
    public void Execute(ref ShootAttack shootAttack)
    {
        shootAttack.onShoot.isTriggered = false;
    }
}

[BurstCompile]
public partial struct ResetHealthEventsJob : IJobEntity
{
    public void Execute(ref Health health)
    {
        health.onHealthChanged = false;
        health.onDead = false;
    }
}

[BurstCompile]
public partial struct ResetMeleeAttackEventsJob : IJobEntity
{
    public void Execute(ref MeleeAttack meleeAttack)
    {
        meleeAttack.onAttack = false;
    }
}

[BurstCompile]
public partial struct ResetBuildingBarracksEventsJob : IJobEntity
{
    /// <summary>
    /// 存储一个单位数量变更的实体列表 用于向非Dots外发送事件(ParallelWriter支持并行写入)
    /// </summary>
    public NativeList<Entity>.ParallelWriter onUnitQueueChangedEntityList;
    public void Execute(ref BuildingBarracks buildingBarracks,Entity entity)
    {
        if(buildingBarracks.onUnitQueueChanged)
        {
            //这里支持并行写入就不能使用Add 需要使用AddNoResize
            onUnitQueueChangedEntityList.AddNoResize(entity);
        }
        buildingBarracks.onUnitQueueChanged = false;
    }
}


[BurstCompile]
[WithOptions(EntityQueryOptions.IgnoreComponentEnabledState)]//忽略组件是否启用
public partial struct ResetSelectedEventsJob : IJobEntity
{
    public void Execute(ref Selected selected)
    {
        selected.onSelected = false;
        selected.onDeselected = false;
    }
}